package com.ygqh.baby.handler;

import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.CodeType;
import com.ygqh.baby.ao.DataStatus;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.OrderStatus;
import com.ygqh.baby.model.SkuBasicData;
import com.ygqh.baby.model.SkuSendSplitRuleBySourceSku;
import com.ygqh.baby.model.SkuSendSplitRuleByTargetSku;
import com.ygqh.baby.model.SplitSendDetailBo;
import com.ygqh.baby.po.YgOrder;
import com.ygqh.baby.po.YgOrderDetail;
import com.ygqh.baby.po.YgOrderSendDetail;
import com.ygqh.baby.redis.RedisDao;
import com.ygqh.baby.service.YgFrameCodeService;
import com.ygqh.baby.service.YgOrderSendDetailService;
import com.ygqh.baby.service.YgOrderService;
import com.ygqh.baby.service.YgSkuService;
import com.ygqh.baby.utils.DateConvertUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 〈〉
 *
 * @author guohao
 * @date 2019/4/17 11:52
 * @since 1.0.0
 */
@Component
public class SplitSendDetailHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private YgFrameCodeService ygFrameCodeService;
    @Autowired
    private YgOrderSendDetailService ygOrderSendDetailService;
    @Autowired
    private YgSkuService ygSkuService;
    @Autowired
    private RedisDao redisDao;


    public static final String SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU = "SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU";
    public static final String SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU = "SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU";

    public Message setSplitRule(SkuSendSplitRuleByTargetSku skuSendSplitRule) {
        Assert.notNull(skuSendSplitRule, "拆分规则不能为空");
        String res = JSON.toJSONString(skuSendSplitRule);
        Long hset = redisDao.hset(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU, skuSendSplitRule.getTargetSkuCode(), res);

        skuSendSplitRule.getPendingSplitSkuList().forEach(item -> {
            SkuSendSplitRuleBySourceSku skuSendSplitRuleBySourceSku = new SkuSendSplitRuleBySourceSku();
            skuSendSplitRuleBySourceSku.setTargetSkuCode(skuSendSplitRule.getTargetSkuCode());
            skuSendSplitRuleBySourceSku.setSendQuantity(skuSendSplitRule.getSendQuantity());
            skuSendSplitRuleBySourceSku.setSendWeekDay(skuSendSplitRule.getSendWeekDay());
            skuSendSplitRuleBySourceSku.setSourceSkuCode(item.getSourceSkuCode());
            skuSendSplitRuleBySourceSku.setTargetQuantity(item.getTargetQuantity());
            skuSendSplitRuleBySourceSku.setHandler(skuSendSplitRule.getHandler());
            skuSendSplitRuleBySourceSku.setUpdateTime(skuSendSplitRule.getUpdateTime());
            String sourceRes = JSON.toJSONString(skuSendSplitRuleBySourceSku);
            redisDao.hset(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU, item.getSourceSkuCode(), sourceRes);
        });

        return Message.success(hset);
    }

    public Message deleteByTargetSku(String targetSkuCode) {
        Assert.notNull(targetSkuCode, "目标skuCode不能为空");

        SkuSendSplitRuleByTargetSku splitRuleByTargetSku = getSplitRuleByTargetSku(targetSkuCode);
        if (splitRuleByTargetSku != null) {
            splitRuleByTargetSku.getPendingSplitSkuList().forEach(item -> redisDao.hdel(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU, item.getSourceSkuCode()));
        }
        Long hdel = redisDao.hdel(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU, targetSkuCode);
        return Message.success(hdel);

    }

    public Message deleteBySourceSku(String sourceSkuCode) {
        Assert.notNull(sourceSkuCode, "目标skuCode不能为空");

        SkuSendSplitRuleBySourceSku splitRuleBySourceSku = getSplitRuleBySourceSku(sourceSkuCode);
        if (splitRuleBySourceSku != null) {
            SkuSendSplitRuleByTargetSku splitRuleByTargetSku = getSplitRuleByTargetSku(splitRuleBySourceSku.getTargetSkuCode());
            splitRuleByTargetSku.getPendingSplitSkuList().removeIf(item -> item.getSourceSkuCode().equals(sourceSkuCode));
            redisDao.hset(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU, splitRuleByTargetSku.getTargetSkuCode(), JSON.toJSONString(splitRuleByTargetSku));
        }
        Long hdel = redisDao.hdel(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU, sourceSkuCode);
        return Message.success(hdel);

    }

    /**
     * 按目标skuCode获取拆分规则
     * 以目标sku 为key
     *
     * @param targetSkuCode 目标skuCode
     * @return SkuSendSplitRuleByTargetSku
     */
    public SkuSendSplitRuleByTargetSku getSplitRuleByTargetSku(String targetSkuCode) {
        SkuSendSplitRuleByTargetSku skuSendSplitRule = null;
        if (StringUtil.isNotBlank(targetSkuCode)) {
            String res = redisDao.hget(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU, targetSkuCode);
            if (StringUtil.isNotBlank(res)) {
                skuSendSplitRule = JSON.parseObject(res, SkuSendSplitRuleByTargetSku.class);
            } else {
                skuSendSplitRule = new SkuSendSplitRuleByTargetSku();
            }
        }
        return skuSendSplitRule;
    }

    /**
     * 按目标skuCode获取拆分规则集合
     *
     * @return List<SkuSendSplitRuleByTargetSku>
     */
    public List<SkuSendSplitRuleByTargetSku> getSplitRuleListByTargetSku(String targetSkuCode) {
        if (StringUtil.isNotBlank(targetSkuCode)) {
            SkuSendSplitRuleByTargetSku skuSendSplitRuleByTargetSku = getSplitRuleByTargetSku(targetSkuCode);
            return Collections.singletonList(skuSendSplitRuleByTargetSku);
        }
        List<String> res = redisDao.hget(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU);
        List<SkuSendSplitRuleByTargetSku> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(res)) {
            for (String str : res) {
                SkuSendSplitRuleByTargetSku skuSendSplitRule = JSON.parseObject(str, SkuSendSplitRuleByTargetSku.class);
                list.add(skuSendSplitRule);
            }
        }
        return list;
    }

    /**
     * 按原skuCode获取拆分规则
     * 以原sku 为key
     *
     * @param sourceSkuCode 目标skuCode
     * @return SkuSendSplitRuleByTargetSku
     */
    public SkuSendSplitRuleBySourceSku getSplitRuleBySourceSku(String sourceSkuCode) {
        SkuSendSplitRuleBySourceSku skuSendSplitRule = null;
        if (StringUtil.isNotBlank(sourceSkuCode)) {
            String res = redisDao.hget(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU, sourceSkuCode);
            if (StringUtil.isNotBlank(res)) {
                skuSendSplitRule = JSON.parseObject(res, SkuSendSplitRuleBySourceSku.class);
            } else {
                skuSendSplitRule = new SkuSendSplitRuleBySourceSku();
            }
        }
        return skuSendSplitRule;
    }

    /**
     * 按原skuCode获取拆分规则集合
     * 以原sku 为key
     *
     * @return List<SkuSendSplitRuleByTargetSku>
     */
    public List<SkuSendSplitRuleBySourceSku> getSplitRuleListBySourceSku(String sourceSkuCode) {
        if (StringUtil.isNotBlank(sourceSkuCode)) {
            SkuSendSplitRuleBySourceSku splitRuleBySourceSku = getSplitRuleBySourceSku(sourceSkuCode);

            return Collections.singletonList(splitRuleBySourceSku);
        }

        List<String> res = redisDao.hget(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_SOURCE_SKU);
        List<SkuSendSplitRuleBySourceSku> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(res)) {
            for (String str : res) {
                SkuSendSplitRuleBySourceSku skuSendSplitRule = JSON.parseObject(str, SkuSendSplitRuleBySourceSku.class);
                list.add(skuSendSplitRule);
            }
        }
        return list;
    }

    /**
     * 是否存在拆分规则
     *
     * @return boolean
     */
    public boolean hasSplitRule() {
        List<String> res = redisDao.hget(SKU_SEND_SPLIT_RULE_REDIS_KEY_BY_TARGET_SKU);
        return CollectionUtils.isNotEmpty(res);
    }

    public int splitSendDetails(Long orderId) {


        if (!hasSplitRule()) {
            logger.info("没有拆分规则，订单：{} 无需拆分");
            return 0;
        }
        boolean existed = ygOrderSendDetailService.existed(orderId);
        if (existed) {
            logger.info("订单 {} 已拆分过，请勿重复操作。");
            return 0;
        }
        try {
            YgOrder order = ygOrderService.findOrderDetailByOrderId(orderId);
            List<SplitSendDetailBo> boList = new ArrayList<>();
            for (YgOrderDetail orderDetail : order.getOrderDetail()) {
                SkuSendSplitRuleBySourceSku splitRuleBySourceSku = getSplitRuleBySourceSku(orderDetail.getSkuCode());
                getSplitRuleBySourceSku(orderDetail.getSkuCode());
                if (splitRuleBySourceSku != null && splitRuleBySourceSku.getTargetSkuCode() != null) {
                    boList.add(buildBo(splitRuleBySourceSku, orderDetail));
                }
            }
            List<YgOrderSendDetail> detailList = buildSendDetail(boList);
            ygOrderSendDetailService.addBatch(detailList);
        } catch (
                Exception e)

        {
            e.printStackTrace();
        }
        return 1;
    }

    private SplitSendDetailBo buildBo(SkuSendSplitRuleBySourceSku detailRule, YgOrderDetail orderDetail) {
        Assert.notNull(detailRule, "拆分规则不能为空");
        Assert.notNull(orderDetail, "订单明细不能为空");
        SplitSendDetailBo splitSendDetailBo = new SplitSendDetailBo();
        splitSendDetailBo.setSendRule(detailRule);
        splitSendDetailBo.setQuantity(detailRule.getTargetQuantity() * orderDetail.getQuantity());
        splitSendDetailBo.setOrderDetail(orderDetail);
        return splitSendDetailBo;

    }

    private List<YgOrderSendDetail> buildSendDetail(List<SplitSendDetailBo> boList) {
        return doBuildSendDetailBySendQuantityOne(boList);
    }


    private List<YgOrderSendDetail> doBuildSendDetailBySendQuantityOne(List<SplitSendDetailBo> boList) {
        Map<String, List<SplitSendDetailBo>> listMap = boList.stream().collect(Collectors.groupingBy(SplitSendDetailBo::getTargetSkuCode));
        List<YgOrderSendDetail> resultList = new ArrayList<>();
        for (Map.Entry<String, List<SplitSendDetailBo>> entry : listMap.entrySet()) {
            SkuBasicData targetSku = ygSkuService.getBasicDataBySkuCode(entry.getKey());
            List<SplitSendDetailBo> detailBos = entry.getValue();
            List<YgOrderSendDetail> detailList = new ArrayList<>();
            SkuSendSplitRuleBySourceSku sendRule = detailBos.get(0).getSendRule();
            Date firstSendTime = getFirstSendTime(sendRule.getSendWeekDay());

            for (SplitSendDetailBo detailBo : detailBos) {
                YgOrderDetail orderDetail = detailBo.getOrderDetail();
                for (int i = 0; i < detailBo.getQuantity(); i++) {
                    YgOrderSendDetail sendDetail = new YgOrderSendDetail();
                    sendDetail.setOrderId(orderDetail.getOrderId());
                    sendDetail.setOdId(orderDetail.getId());
                    sendDetail.setSupplierId(targetSku.getSupplierId());
                    sendDetail.setProductId(targetSku.getProductId());
                    sendDetail.setProductName(targetSku.getProductName());
                    sendDetail.setColor(targetSku.getColor());
                    sendDetail.setSkuId(targetSku.getSkuId());
                    sendDetail.setSkuCode(targetSku.getSkuCode());
                    sendDetail.setSizeName(targetSku.getSizeName());
                    sendDetail.setImageUrl(targetSku.getMainImageUrl());
                    sendDetail.setQuantity(sendRule.getSendQuantity());
                    sendDetail.setCreateBy("sys");
                    sendDetail.setCreateTime(new Date());
                    sendDetail.setUpdateTime(sendDetail.getCreateTime());
                    sendDetail.setUpdateBy("sys");
                    sendDetail.setStatus(DataStatus.Valid.name());
                    sendDetail.setOrderStatus(OrderStatus.WaitingSend.name());
                    detailList.add(sendDetail);
                }
            }

            for (int i = 0; i < detailList.size(); i++) {
                YgOrderSendDetail sendDetail = detailList.get(i);
                sendDetail.setNeedSendTime(DateConvertUtils.addDay(firstSendTime, i * 7));
            }
            resultList.addAll(detailList);

            setSubId(resultList);
        }
        return resultList;
    }

    private void setSubId(List<YgOrderSendDetail> list) {
        //按商家 ，发货时间拆分
        Map<String, List<YgOrderSendDetail>> listMap = list.stream().collect(Collectors.groupingBy(detail ->
                detail.getSupplierId() + "-" + DateConvertUtils.format(detail.getNeedSendTime())));
        for (Map.Entry<String, List<YgOrderSendDetail>> entry : listMap.entrySet()) {
            entry.getValue().forEach(detail -> {
                Long subId = ygFrameCodeService.getFrameCode(CodeType.Order, new Date());
                detail.setSubId(subId);
            });
        }
    }

    private Date getFirstSendTime(int sendWeekDay) {
        Assert.isTrue(sendWeekDay > 0 && sendWeekDay <= 7, "超出每周日期范围");
//        int weekDay = DateConvertUtils.getWeekDay(new Date());
        Date sendTime;
        sendTime = DateConvertUtils.getNextWeekDate(sendWeekDay);
//        if (weekDay >= sendWeekDay) {
//            sendTime = DateConvertUtils.getNextWeekDate(sendWeekDay);
//        } else {
//            sendTime = DateConvertUtils.getCurrentWeekDate(sendWeekDay);
//        }
        return sendTime;
    }

    public static void main(String[] args) {
        BigDecimal splitCount = new BigDecimal(10).divide(new BigDecimal(3), 0, BigDecimal.ROUND_UP);
        System.out.println(splitCount.intValue());
        Date nextWeekDate = DateConvertUtils.getCurrentWeekDate(1);
        System.out.println(DateConvertUtils.formatDateTime(nextWeekDate));

        List<YgOrderSendDetail> list = new ArrayList<>();

        YgOrderSendDetail sendDetail = new YgOrderSendDetail();

        sendDetail.setNeedSendTime(new Date());
        list.add(sendDetail);

        Map<String, List<YgOrderSendDetail>> listMap = list.stream().collect(Collectors.groupingBy(detail -> DateConvertUtils.format(detail.getNeedSendTime())));
        for (Map.Entry<String, List<YgOrderSendDetail>> entry : listMap.entrySet()) {
            entry.getValue().forEach(detail -> {
                detail.setSubId(1L);
            });
        }
        System.out.println(JSON.toJSONString(list));
    }
}
